﻿using System;
using System.Collections.Generic;
using System.Text;

namespace CoreRay
{
    /// <summary>
    /// The GeometryObject class defines a scene object that can be positioned in a 3D space.
    /// It has methods used for rendering and also stores local and world bounding boxes.
    /// </summary>
    public abstract class GeometryObject : SceneObject
    {
        private Matrix worldMatrix;
        private Matrix inversedWorldMatrix;
        private BoundingBox boundingBox;
        private BoundingBox worldBoundingBox;

        protected GeometryObject()
        {
            this.Name = "Unknown GeometryObject";
            this.UseWorldMatrix = true;
        }

        public BoundingBox WorldBoundingBox
        {
            get
            {
                if (this.worldBoundingBox == null)
                {
                    this.worldBoundingBox = this.BoundingBox * this.WorldMatrix;
                }

                return this.worldBoundingBox;
            }
        }

        public bool UseWorldMatrix
        {
            get;
            protected set;
        }

        public BoundingBox BoundingBox
        {
            get
            {
                return this.boundingBox;
            }

            protected set
            {
                this.boundingBox = value;
                this.worldBoundingBox = null;
            }
        }

        public Matrix WorldMatrix
        {
            get
            {
                if (this.worldMatrix == null)
                {
                    return Matrix.Identity;
                }

                return this.worldMatrix;
            }

            set
            {
                this.worldMatrix = value;
                this.inversedWorldMatrix = null;
                this.worldBoundingBox = null;
            }
        }

        public Matrix InversedWorldMatrix
        {
            get
            {
                if (this.inversedWorldMatrix == null)
                {
                    this.inversedWorldMatrix = this.WorldMatrix.Inverse();
                }

                return this.inversedWorldMatrix;
            }
        }

        public abstract Intersection Intersect(Ray ray);

        public abstract bool IntersectPosition(Ray ray);
    }
}
